# JWT认证控制器
from flask import Blueprint, request, jsonify, current_app
from app.utils.jwt_utils import JWTUtils, token_required, admin_required
from app.utils.response import response_success, response_fail
from app.utils.redis_utils import RedisUtils
from app.models.user import User
from app.extensions import db
import uuid

from flask_login import login_required

# 创建认证蓝图
auth_bp = Blueprint('auth', __name__, url_prefix='/auth')

@auth_bp.route('/login', methods=['POST'])
def login():
    """用户登录，返回JWT令牌"""
    try:
        data = request.get_json()
        username = data.get('username')
        password = data.get('password')
        
        if not username or not password:
            return response_fail(msg="用户名和密码不能为空")
        
        # 从数据库查询用户
        user = User.query.filter_by(username=username).first()
        
        # 验证用户
        if not user or not user.check_password(password):
            return response_fail(msg="用户名或密码错误")
        
        # 检查用户是否激活
        if not user.is_active:
            return response_fail(msg="用户账户已被禁用")
        
        # 生成JWT令牌
        token_payload = {
            'user_id': user.id,
            'username': user.username,
            'is_admin': user.is_admin
        }
        
        token = JWTUtils.generate_token(token_payload)
        
        # 生成唯一的token ID，用于Redis存储
        token_id = str(uuid.uuid4())
        
        # 将token存储到Redis中，使用7号数据库
        token_data = {
            'token': token,
            'user_id': user.id,
            'username': user.username,
            'is_admin': user.is_admin,
            'token_id': token_id
        }
        
        # 存储到Redis，设置过期时间为24小时（86400秒）
        redis_key = f"auth:token:{token_id}"
        redis_success = RedisUtils.set(redis_key, token_data, timeout=86400)
        
        if not redis_success:
            current_app.logger.error("存储token到Redis失败")
            # 即使Redis存储失败，也继续返回token，不影响登录流程
        
        return response_success(data={
            'token': token,
            'token_id': token_id,
            'user': {
                'id': user.id,
                'username': user.username,
                'email': user.email,
                'is_admin': user.is_admin
            }
        }, msg="登录成功")
    
    except Exception as e:
        import traceback
        error_details = traceback.format_exc()
        print(f"登录错误详情: {error_details}")
        return response_fail(msg=f"登录失败: {str(e)}")

@auth_bp.route('/register', methods=['POST'])
def register():
    """用户注册"""
    try:
        data = request.get_json()
        username = data.get('username')
        password = data.get('password')
        email = data.get('email')
        
        if not username or not password:
            return response_fail(msg="用户名和密码不能为空")
        
        if not email:
            return response_fail(msg="邮箱不能为空")
        
        # 检查用户名是否已存在
        if User.query.filter_by(username=username).first():
            return response_fail(msg="用户名已存在")
            
        # 检查邮箱是否已存在
        if User.query.filter_by(email=email).first():
            return response_fail(msg="邮箱已被注册")
        
        # 创建新用户
        new_user = User(
            username=username,
            email=email,
            is_admin=False,
            is_active=True
        )
        new_user.set_password(password)
        
        # 保存到数据库
        db.session.add(new_user)
        db.session.commit()
        
        return response_success(data={
            'user': {
                'id': new_user.id,
                'username': new_user.username,
                'email': new_user.email
            }
        }, msg="注册成功")
    
    except Exception as e:
        db.session.rollback()
        return response_fail(msg=f"注册失败: {str(e)}")

@auth_bp.route('/refresh', methods=['POST'])
def refresh_token():
    """刷新JWT令牌"""
    try:
        data = request.get_json()
        token = data.get('token')
        
        if not token:
            return response_fail(msg="令牌不能为空")
        
        # 刷新令牌
        new_token = JWTUtils.refresh_token(token)
        
        if not new_token:
            return response_fail(msg="令牌无效或刷新失败")
        
        return response_success(data={
            'token': new_token
        }, msg="令牌刷新成功")
    
    except Exception as e:
        return response_fail(msg=f"令牌刷新失败: {str(e)}")

@auth_bp.route('/logout', methods=['POST'])
def logout():
    """用户登出，从Redis中删除token"""
    try:
        data = request.get_json()
        token_id = data.get('token_id')
        
        if not token_id:
            return response_fail(msg="token_id不能为空")
        
        # 从Redis中删除token
        redis_key = f"auth:token:{token_id}"
        redis_success = RedisUtils.delete(redis_key)
        
        if redis_success:
            return response_success(msg="登出成功")
        else:
            return response_fail(msg="登出失败，token可能已过期或不存在")
    
    except Exception as e:
        return response_fail(msg=f"登出失败: {str(e)}")

@auth_bp.route('/verify', methods=['POST'])
def verify_token():
    """验证JWT令牌"""
    try:
        data = request.get_json()
        token = data.get('token')
        token_id = data.get('token_id')
        
        if not token:
            return response_fail(msg="令牌不能为空")
        
        # 验证令牌
        payload = JWTUtils.verify_token(token)
        
        if not payload:
            return response_fail(msg="令牌无效或已过期")
        
        # 如果提供了token_id，也验证Redis中是否存在
        redis_valid = True
        if token_id:
            redis_key = f"auth:token:{token_id}"
            redis_data = RedisUtils.get(redis_key)
            if not redis_data:
                redis_valid = False
        
        return response_success(data={
            'valid': True,
            'redis_valid': redis_valid,
            'payload': payload
        }, msg="令牌验证成功")
    
    except Exception as e:
        return response_fail(msg=f"令牌验证失败: {str(e)}")

@auth_bp.route('/decode', methods=['POST'])
def decode_token():
    """解码JWT令牌（不验证签名，仅用于调试）"""
    try:
        data = request.get_json()
        token = data.get('token')
        
        if not token:
            return response_fail(msg="令牌不能为空")
        
        # 解码令牌
        payload = JWTUtils.decode_token_without_verification(token)
        
        if not payload:
            return response_fail(msg="令牌解码失败")
        
        return response_success(data={
            'payload': payload
        }, msg="令牌解码成功")
    
    except Exception as e:
        return response_fail(msg=f"令牌解码失败: {str(e)}")

@auth_bp.route('/profile', methods=['GET'])
@token_required
def get_profile():
    """获取当前用户信息（需要认证）"""
    try:
        # 从请求上下文获取用户信息
        user = request.current_user
        
        # 从数据库获取完整用户信息
        user_info = User.query.get(user['user_id'])
        if not user_info:
            return response_fail(msg="用户不存在")
        
        return response_success(data={
            'user': {
                'id': user_info.id,
                'username': user_info.username,
                'email': user_info.email,
                'is_admin': user_info.is_admin,
                'is_active': user_info.is_active,
                'created_at': user_info.created_at.isoformat() if user_info.created_at else None,
                'updated_at': user_info.updated_at.isoformat() if user_info.updated_at else None
            }
        }, msg="获取用户信息成功")
    
    except Exception as e:
        return response_fail(msg=f"获取用户信息失败: {str(e)}")

@auth_bp.route('/admin-only', methods=['GET'])
@admin_required
def admin_only():
    """仅管理员可访问的路由"""
    try:
        # 从请求上下文获取用户信息
        user = request.current_user
        
        # 从数据库获取用户信息
        user_info = User.query.get(user['user_id'])
        if not user_info:
            return response_fail(msg="用户不存在")
        
        return response_success(data={
            'message': '这是管理员专用内容',
            'admin_user': {
                'id': user_info.id,
                'username': user_info.username,
                'email': user_info.email
            }
        }, msg="管理员验证成功")
    
    except Exception as e:
        return response_fail(msg=f"访问失败: {str(e)}")

@auth_bp.route('/users', methods=['GET'])
@admin_required
def get_all_users():
    """获取所有用户列表（仅管理员）"""
    try:
        # 从数据库获取所有用户
        users = User.query.all()
        
        # 转换用户数据为列表，去除密码
        users_list = []
        for user in users:
            users_list.append({
                'id': user.id,
                'username': user.username,
                'email': user.email,
                'is_admin': user.is_admin,
                'is_active': user.is_active,
                'created_at': user.created_at.isoformat() if user.created_at else None,
                'updated_at': user.updated_at.isoformat() if user.updated_at else None
            })
        
        return response_success(data={
            'users': users_list,
            'count': len(users_list)
        }, msg="获取用户列表成功")
    
    except Exception as e:
        return response_fail(msg=f"获取用户列表失败: {str(e)}")